﻿using System;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Linq;
using System.Reflection.Emit;
using System.Collections.Generic;

namespace ui
{
    public class cs2Dreflection
    {
        public object createClass(string name)
        {
            return Assembly.GetExecutingAssembly().CreateInstance(name);
        }

        public List<string> getClasses(string ns)
        {
            List<string> list = new List<string>();
            var q = from t in Assembly.GetExecutingAssembly().GetTypes()
                    where t.IsClass && t.Namespace == ns
                    select t;
            q.ToList().ForEach(t => list.Add(t.FullName));
            return list;
        }

        public FieldInfo[] getVariables(object obj)
        {
            Type typ = obj.GetType();
            FieldInfo[] prop = typ.GetFields();
            return prop;
        }

        public MethodInfo[] getMethods(object obj)
        {
            Type typ = obj.GetType();
            MethodInfo[] prop = typ.GetMethods();
            return prop;
        }

        public string evaluateExpression(string expression)
        {
            string code = string.Format
            (
                "using System;public static class Func{{ public static double func(){{ return {0};}}}}",
                expression
            );

            CompilerResults compilerResults = compileScript(code);

            if (compilerResults.Errors.HasErrors)
            {
                throw new InvalidOperationException("Expression has a syntax error.");
            }

            Assembly assembly = compilerResults.CompiledAssembly;
            MethodInfo method = assembly.GetType("Func").GetMethod("func");

            string result = method.Invoke(null, null).ToString();
            return result;
        }

        public int runMethod(Assembly assembly, string classname, string function)
        {
            MethodInfo method = assembly.GetType(classname).GetMethod(function);
            return (int)method.Invoke(null, null);
        }

        public CompilerResults compileScript(string source)
        {
            CompilerParameters parms = new CompilerParameters();

            parms.GenerateExecutable = false;
            parms.GenerateInMemory = true;
            parms.IncludeDebugInformation = true;

            foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (asm.Location != "")
                {
                    parms.ReferencedAssemblies.Add(asm.Location);
                }
            }

            CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");

            return compiler.CompileAssemblyFromSource(parms, source);
        }
    }
}